#ifndef SEMINIX_GFP_H
#define SEMINIX_GFP_H

#include <utils/types.h>
#include <seminix/mmdebug.h>
#include <seminix/mmzone.h>

typedef unsigned int __bitwise gfp_t;

/* zone index */
#define __GFP_DMA			BIT(0)
#define __GFP_NORMAL		BIT(1)

/* page alloc feature */
#define __GFP_ZERO			BIT(2)
#define __GFP_NOWARN		BIT(3)

/* space select */
#define __GFP_KERNEL		BIT(4)
#define __GFP_USER			BIT(5)
#define GFP_SPACE_SHIFT     4
#define GFP_SPACE_MASK      (__GFP_KERNEL | __GFP_USER)

#define __GFP_BITS_SHIFT	6
#define __GFP_BITS_MASK 	((gfp_t)((1 << __GFP_BITS_SHIFT) - 1))

#define GFP_DMA			    ((gfp_t)__GFP_DMA)
#define GFP_NORMAL		    ((gfp_t)__GFP_NORMAL)

#define GFP_ZERO			((gfp_t)__GFP_ZERO)
#define GFP_NOWARN		    ((gfp_t)__GFP_NOWARN)

#define GFP_KERNEL		    ((gfp_t)__GFP_KERNEL)
#define GFP_USER			((gfp_t)__GFP_USER)

static inline enum zone_type gfp_zone(gfp_t flags)
{
    if (unlikely(GFP_DMA & flags))
        return ZONE_DMA;

    return ZONE_NORMAL;
}

extern void __free_pages(struct page *page, unsigned int order);
extern void free_pages(unsigned long addr, unsigned int order);

#define __free_page(page) __free_pages((page), 0)
#define free_page(addr) free_pages((addr), 0)


extern struct page *__alloc_pages(gfp_t gfp_mask, unsigned int order);

#define alloc_pages(gfp_mask, order)	__alloc_pages(gfp_mask, order)
#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)

extern unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order);

#define __get_free_page(gfp_mask) \
        __get_free_pages((gfp_mask), 0)

#endif /* !SEMINIX_GFP_H */
